home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 076-100 / 092 / bawk / bawkdo.c < prev    next >
C/C++ Source or Header  |  1995-03-13  |  10KB  |  477 lines

  1. /*
  2.  * Bawk C actions interpreter
  3.  */
  4. #include <stdio.h>
  5. #include "bawk.h"
  6.  
  7. static char pop_array[MAX_TOKEN + 1];
  8.  
  9. void init_pop_array()
  10. {
  11.     register int i;
  12.  
  13.     DBUG_ENTER("init_pop_array");
  14.     for(i = 0; i <= MAX_TOKEN; i++)
  15.         pop_array[i] = 1;
  16.     pop_array[T_STATEMENT] = pop_array[T_IF] = pop_array[T_DECLARE] = 0;
  17.     pop_array[T_DECLARE] = pop_array[T_ARRAY_DECLARE] = 0;
  18.     pop_array[T_BREAK] = 0;
  19.     DBUG_VOID_RETURN;
  20. }
  21.  
  22. int dopattern( root )
  23. register EXPR_NODE *root;
  24. {
  25.     DBUG_ENTER("dopattern");
  26.     Where = PATTERN;
  27.     walk_tree(root);
  28.     DBUG_RETURN(popint());
  29. }
  30.  
  31. void doaction( root )
  32. register EXPR_NODE *root;
  33. {
  34.     DBUG_ENTER("doaction");
  35.     Where = ACTION;
  36.     walk_tree(root);
  37.     DBUG_VOID_RETURN;
  38. }
  39.  
  40. void walk_tree(root)
  41. register EXPR_NODE *root;
  42. {
  43.     register int ival;
  44.     DATUM data;
  45.     register VARIABLE *pvar;
  46.     register VARDECL *pdecl;
  47.  
  48.     DBUG_ENTER("walk_tree");
  49.     if(Saw_break || !root)
  50.         DBUG_VOID_RETURN;
  51.     switch(root->operator) {
  52.     case T_ASSIGN:
  53.         walk_tree(root->left);
  54.         walk_tree(root->right);
  55.         assignment();
  56.         break;
  57.     case T_LOR:
  58.         walk_tree(root->left);
  59.         if(popint())
  60.             pushint(1);
  61.         else {
  62.             walk_tree(root->right);
  63.             pushint(popint() != 0);
  64.         }
  65.         break;
  66.     case T_LAND:
  67.         walk_tree(root->left);
  68.         if(!popint())
  69.             pushint(0);
  70.         else {
  71.             walk_tree(root->right);
  72.             pushint(popint() != 0);
  73.         }
  74.         break;
  75.     case T_OR:
  76.         walk_tree(root->left);
  77.         walk_tree(root->right);
  78.         pushint(popint() | popint());
  79.         break;
  80.     case T_AND:
  81.         walk_tree(root->left);
  82.         walk_tree(root->right);
  83.         pushint(popint() & popint());
  84.         break;
  85.     case T_XOR:
  86.         walk_tree(root->left);
  87.         walk_tree(root->right);
  88.         pushint(popint() ^ popint());
  89.         break;
  90.     case T_EQ:
  91.         walk_tree(root->left);
  92.         walk_tree(root->right);
  93.         pushint(popint() == popint());
  94.         break;
  95.     case T_NE:
  96.         walk_tree(root->left);
  97.         walk_tree(root->right);
  98.         pushint(popint() != popint());
  99.         break;
  100.     case T_LE:
  101.         walk_tree(root->left);
  102.         ival = popint();
  103.         walk_tree(root->right);
  104.         pushint(ival <= popint());
  105.         break;
  106.     case T_GE:
  107.         walk_tree(root->left);
  108.         ival = popint();
  109.         walk_tree(root->right);
  110.         pushint(ival >= popint());
  111.         break;
  112.     case T_LT:
  113.         walk_tree(root->left);
  114.         ival = popint();
  115.         walk_tree(root->right);
  116.         pushint(ival < popint());
  117.         break;
  118.     case T_GT:
  119.         walk_tree(root->left);
  120.         ival = popint();
  121.         walk_tree(root->right);
  122.         pushint(ival > popint());
  123.         break;
  124.     case T_SHL:
  125.         walk_tree(root->left);
  126.         ival = popint();
  127.         walk_tree(root->right);
  128.         pushint(ival << popint());
  129.         break;
  130.     case T_SHR:
  131.         walk_tree(root->left);
  132.         ival = popint();
  133.         walk_tree(root->right);
  134.         pushint(ival >> popint());
  135.         break;
  136.     case T_ADD:
  137.         walk_tree(root->left);
  138.         walk_tree(root->right);
  139.         pushint(popint() + popint());
  140.         break;
  141.     case T_SUB:
  142.         walk_tree(root->left);
  143.         ival = popint();
  144.         walk_tree(root->right);
  145.         pushint(ival - popint());
  146.         break;
  147.     case T_MUL:
  148.         walk_tree(root->left);
  149.         ival = popint();
  150.         walk_tree(root->right);
  151.         pushint(ival * popint());
  152.         break;
  153.     case T_DIV:
  154.         walk_tree(root->left);
  155.         ival = popint();
  156.         walk_tree(root->right);
  157.         pushint(ival / popint());
  158.         break;
  159.     case T_MOD:
  160.         walk_tree(root->left);
  161.         ival = popint();
  162.         walk_tree(root->right);
  163.         pushint(ival % popint());
  164.         break;
  165.     case T_LNOT:
  166.         walk_tree(root->left);
  167.         pushint( ! popint() );
  168.         break;
  169.     case T_NOT:
  170.         walk_tree(root->left);
  171.         pushint( ~ popint() );
  172.         break;
  173.     case T_INCR:
  174.         walk_tree(root->left);
  175.         preincdec(1);
  176.         break;
  177.     case T_DECR:
  178.         walk_tree(root->left);
  179.         preincdec(-1);
  180.         break;
  181.     case T_DOLLAR:
  182.         /*
  183.          * It's a reference to one (or all) of the words in Linebuf.
  184.          */
  185.         walk_tree(root->left);
  186.         if ( ival = popint() )
  187.         {
  188.             if ( ival > Fieldcount )
  189.                 ival = Fieldcount;
  190.             else if ( ival < 1 )
  191.                 ival = 1;
  192.             data.dptr = Fields[ ival-1 ];
  193.         }
  194.         else
  195.         {
  196.             /*
  197.              * Reconstitute the line buffer in case any of the
  198.              * fields have been changed.
  199.              */
  200.             unparse( Fields, Fieldcount, Linebuf, Fieldsep );
  201.             data.dptr = Linebuf;
  202.         }
  203.         /*
  204.          * $<expr>'s are treated the same as string constants:
  205.          */
  206.         push( (char) 1, (char) ACTUAL, (char) BYTE, &data );
  207.         break;
  208.     case T_UMINUS:
  209.         walk_tree(root->left);
  210.         pushint( - popint() );
  211.         break;
  212.     case T_STAR:
  213.         walk_tree(root->left);
  214.         /*
  215.          * If item on stack is an LVALUE, do an extra level of
  216.          * indirection before changing it to an LVALUE.
  217.          */
  218.         if ( Stackptr->lvalue )
  219.             Stackptr->value.ptrptr = 
  220.                 (char **) *Stackptr->value.ptrptr;
  221.         Stackptr->lvalue = 1;
  222.         --Stackptr->class;
  223.         break;
  224.     case T_ADDROF:
  225.         walk_tree(root->left);
  226.         if ( Stackptr->lvalue )
  227.             Stackptr->lvalue = 0;
  228.         else
  229.             error( "'&' operator needs an lvalue", ACT_ERROR );
  230.         break;
  231.     case T_CONSTANT:
  232.         pushint(((DATUM *) (root->left))->ival);
  233.         break;
  234.     case T_FUNCTION:
  235.         function(((DATUM *) (root->left))->ival, root->right);
  236.         break;
  237.     case T_REGEXP:
  238.         /*
  239.          * Perform a match of the regular expression agains input
  240.          * line.
  241.          */
  242.         unparse( Fields, Fieldcount, Linebuf, Fieldsep );
  243.         pushint( match( Linebuf, (char *) root->left ) );
  244.         break;
  245.     case T_REGEXP_ARG:
  246.         /*
  247.          * A regular expression that is to be passed as a function
  248.          * argument.
  249.          */
  250.         data.dptr = (char *) root->left;
  251.         push( (char) 1, (char) ACTUAL, (char) BYTE, &data );
  252.         break;
  253.     case T_STRING:
  254.         data.dptr = (char *) root->left;
  255.         push( (char) 1, (char) ACTUAL, (char) BYTE, &data );
  256.         break;
  257.     case T_NF:
  258.         pushint( Fieldcount );
  259.         break;
  260.     case T_NR:
  261.         pushint( Recordcount );
  262.         break;
  263.     case T_FS:
  264.         data.dptr = Fieldsep;
  265.         push( (char) 1, (char) ACTUAL, (char) BYTE, &data );
  266.         break;
  267.     case T_RS:
  268.         data.dptr = Recordsep;
  269.         push( (char) 1, (char) ACTUAL, (char) BYTE, &data );
  270.         break;
  271.     case T_FILENAME:
  272.         data.dptr = Filename;
  273.         push( (char) 1, (char) ACTUAL, (char) BYTE, &data );
  274.         break;
  275.     case T_VARIABLE:
  276.         pvar = (VARIABLE *) root->left;
  277.         /*
  278.          * it's a plain variable. The way a variable is
  279.          * represented on the stack depends on its type:
  280.          *      lvalue class value.dptr
  281.          * vars:  1      0   address of var
  282.          * ptrs:  1      1   ptr to address of ptr
  283.          * array: 0      1   address of var
  284.          */
  285.         if ( pvar->vclass && !pvar->vlen )
  286.             /* it's a pointer */
  287.             data.dptr = (char *) &pvar->vptr;
  288.         else
  289.             /* an array or simple variable */
  290.             data.dptr = pvar->vptr;
  291.         /*
  292.          * If it's an array it can't be used as an LVALUE.
  293.          */
  294.         push( pvar->vclass, (char) !pvar->vlen, pvar->vsize, &data );
  295.         break;
  296.     case T_LBRACKET:
  297.         walk_tree(root->left);
  298.         if ( ! Stackptr->class )
  299.             error( "'[]' needs an array or pointer", ACT_ERROR );
  300.         /*
  301.          * compute the subscript
  302.          */
  303.         walk_tree(root->right);
  304.         ival = popint();
  305.         /*
  306.          * compute the offset (subscript times WORD for int arrays)
  307.          * and then the effective address.
  308.          */
  309.         ival *= Stackptr->size;
  310.         if ( Stackptr->lvalue )
  311.             /*
  312.              * It's a pointer - don't forget that the stack top
  313.              * item's value is the address of the pointer so we
  314.              * must do another level of indirection.
  315.              */
  316.             Stackptr->value.dptr = *Stackptr->value.ptrptr+ival;
  317.         else
  318.             /*
  319.              * It's a plain array - the stack top item's value is
  320.              * the address of the first element in the array.
  321.              */
  322.             Stackptr->value.dptr += ival;
  323.  
  324.         /*
  325.          * The stack top item now becomes an LVALUE, but we've
  326.          * reduced the indirection level.
  327.          */
  328.         Stackptr->lvalue = 1;
  329.         --Stackptr->class;
  330.         break;
  331.     case T_POSTINCR:
  332.         walk_tree(root->left);
  333.         postincdec(1);
  334.         break;
  335.     case T_POSTDECR:
  336.         walk_tree(root->left);
  337.         postincdec(-1);
  338.         break;
  339.     case T_STATEMENT:
  340.         if(root->left) {
  341.             walk_tree(root->left);
  342.             if(pop_array[root->left->operator])
  343.                 popint();
  344.         }
  345.         walk_tree(root->right);
  346.         break;
  347.     case T_DECLARE:
  348.         pdecl = (VARDECL *) root->left;
  349.         pvar = pdecl->variable;
  350.         if(pdecl->vsize != ((pvar->vlen ? pvar->vlen : 1)*
  351.                     pvar->vsize)) {
  352.             /*
  353.              * The amount of storage needed for the variable has
  354.              * changed.
  355.              */
  356.             free(pvar->vptr);
  357.             pvar->vptr = get_clear_memory(pdecl->vsize);
  358.         }
  359.         pvar->vclass = pdecl->vclass;
  360.         pvar->vsize = pdecl->vsize;
  361.         pvar->vlen = 0;
  362.         walk_tree(root->right);
  363.         break;
  364.     case T_ARRAY_DECLARE:
  365.         /* Compute the dimension */
  366.         walk_tree(root->left->right);
  367.         ival = popint();
  368.         pdecl = (VARDECL *) root->left->left;
  369.         pvar = pdecl->variable;
  370.         if((ival*pdecl->vsize) != ((pvar->vlen ? pvar->vlen : 1)*
  371.                     pvar->vsize)) {
  372.             free(pvar->vptr);
  373.             pvar->vptr = get_clear_memory(ival*pdecl->vsize);
  374.         }
  375.         pvar->vclass = pdecl->vclass;
  376.         pvar->vsize = pdecl->vsize;
  377.         pvar->vlen = ival;
  378.         walk_tree(root->right);
  379.         break;
  380.     case T_IF:
  381.         walk_tree(root->left->left);
  382.         if(popint())
  383.             walk_tree(root->left->right);
  384.         else
  385.             walk_tree(root->right);
  386.         break;
  387.     case T_WHILE:
  388.         while( !Saw_break )
  389.         {
  390.             walk_tree(root->left);
  391.             if( ! popint() )
  392.                 break;
  393.             walk_tree(root->right);
  394.         }
  395.         Saw_break = 0;
  396.         break;
  397.     case T_BREAK:
  398.         Saw_break = 1;
  399.         break;
  400.     default:
  401.         DBUG_PRINT("walk_tree",
  402.             ("decimal value of operator = %d",root->operator));
  403.         error("internal error: parse tree node with unknown symbol",
  404.               ACT_ERROR);
  405.     }
  406.     DBUG_VOID_RETURN;
  407. }
  408.  
  409. void preincdec(incr)
  410. register int incr;
  411. {
  412.     /*
  413.      * Pre increment/decrement
  414.      */
  415.     DBUG_ENTER("preincdec");
  416.     if ( Stackptr->lvalue )
  417.     {
  418.         if ( Stackptr->class )
  419.             incr *= Stackptr->size;
  420.         *Stackptr->value.ptrptr += incr;
  421.     }
  422.     else
  423.         error( "pre '++' or '--' needs an lvalue", ACT_ERROR );
  424.     DBUG_VOID_RETURN;
  425. }
  426.  
  427.  
  428. void postincdec(incr)
  429. register int incr;
  430. {
  431.     /*
  432.      * Post increment/decrement
  433.      */
  434.     register char **pp;
  435.  
  436.     DBUG_ENTER("postincdec");
  437.     if ( Stackptr->lvalue )
  438.     {
  439.         if ( Stackptr->class )
  440.         {
  441.             /*
  442.              * It's a pointer - save its old value then
  443.              * increment/decrement the pointer.  This makes the
  444.              * item on top of the stack look like an array, which
  445.              * means it can no longer be used as an LVALUE. This
  446.              * doesn't really hurt, since it doesn't make much
  447.              * sense to say:
  448.              *   char *cp;
  449.              *   cp++ = value;
  450.              */
  451.             pp = (char **) *Stackptr->value.ptrptr;
  452.             *Stackptr->value.ptrptr += incr * Stackptr->size;
  453.             Stackptr->value.ptrptr = pp;
  454.         }
  455.         else
  456.         {
  457.             /*
  458.              * It's a simple variable - save its old value then
  459.              * increment/decrement the variable.  This makes the
  460.              * item on top of the stack look like a constant,
  461.              * which means it can no longer be used as an LVALUE.
  462.              * Same reasoning as above.
  463.              */
  464.             if ( Stackptr->size == BYTE )
  465.                 pp = (char **) *Stackptr->value.dptr;
  466.             else
  467.                 pp = (char **) *Stackptr->value.ptrptr;
  468.             *Stackptr->value.ptrptr += incr;
  469.             Stackptr->value.ptrptr = pp;
  470.         }
  471.         Stackptr->lvalue = 0;
  472.     }
  473.     else
  474.         error( "post '++' or '--' needs an lvalue", ACT_ERROR );
  475.     DBUG_VOID_RETURN;
  476. }
  477.